package org.example.utils;


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.example.domain.system.constant.SecurityConstant;
import org.example.domain.system.constant.TokenConstants;
import org.example.domain.system.model.LoginUser;
import org.example.domain.system.text.Convert;
import org.springframework.http.server.reactive.ServerHttpRequest;

import javax.crypto.SecretKey;
import java.util.Map;

/**
 * Jwt工具类
 */
public class JwtUtils {
    // 使用 Keys.hmacShaKeyFor 生成 SecretKey 实例
    private static final SecretKey secretKey = Keys.hmacShaKeyFor(TokenConstants.SECRET.getBytes());


    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    public static String createToken(Map<String, Object> claims) {
        return Jwts.builder().claims(claims).signWith(secretKey).compact();
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    public static Claims parseToken(String token) {
        return Jwts.parser()
                .verifyWith(secretKey)
                .build()
                .parseSignedClaims(token).getPayload();
    }

    /**
     * 根据令牌获取用户Token
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static String getTokenKey(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstant.SECURITY_TOKEN_KEY);
    }

    /**
     * 根据令牌获取用户Token
     *
     * @param claims 身份信息
     * @return 用户ID
     */
    public static String getTokenKey(Claims claims) {
        return getValue(claims, SecurityConstant.SECURITY_TOKEN_KEY);
    }

    /**
     * 根据令牌获取用户ID
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static String getUserId(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstant.SECURITY_USER_ID);
    }

    /**
     * 根据身份信息获取用户ID
     *
     * @param claims 身份信息
     * @return 用户ID
     */
    public static String getUserId(Claims claims) {
        return getValue(claims, SecurityConstant.SECURITY_USER_ID);
    }

    /**
     * 根据令牌获取用户名
     *
     * @param token 令牌
     * @return 用户名
     */
    public static String getUserName(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstant.SECURITY_USER_NAME);
    }

    /**
     * 根据身份信息获取用户名
     *
     * @param claims 身份信息
     * @return 用户名
     */
    public static String getUserName(Claims claims) {
        return getValue(claims, SecurityConstant.SECURITY_USER_NAME);
    }


    /**
     * 根据令牌获取登录源
     *
     * @param token 令牌
     * @return 用户名
     */
    public static String getLoginType(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstant.SECURITY_LOGIN_TYPE);
    }

    /**
     * 根据身份信息获取登录源
     *
     * @param claims 身份信息
     * @return 用户名
     */
    public static String getLoginType(Claims claims) {
        return getValue(claims, SecurityConstant.SECURITY_LOGIN_TYPE);
    }

    /**
     * 根据身份信息获取键值
     *
     * @param claims 身份信息
     * @param key    键
     * @return 值
     */
    public static String getValue(Claims claims, String key) {
        return Convert.toStr(claims.get(key), "");
    }

    public static String getToken(ServerHttpRequest request)
    {
        String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION);
        // 如果前端设置了令牌前缀，则裁剪掉前缀
        if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX))
        {
            token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY);
        }
        return token;
    }


    /**
     * 根据令牌获取登录用户信息
     *
     * @param token 令牌
     * @return 用户名
     */
    public static LoginUser getLoginUser(String token) {
        Claims claims = parseToken(token);
        return claims.get(SecurityConstant.SECURITY_LOGIN_USER, LoginUser.class);
    }

    /**
     * 根据身份信息获取登录用户信息
     *
     * @param claims 身份信息
     * @return 用户名
     */
    public static LoginUser getLoginUser(Claims claims) {
        return claims.get(SecurityConstant.SECURITY_LOGIN_USER, LoginUser.class);
    }


}
